use lazy_static::lazy_static;
use std::{
    ffi::{CStr, c_int},
    os::raw::c_char,
    sync::{
        Mutex,
        mpsc::{self, Receiver, Sender},
    },
    thread::{self, JoinHandle},
};
type RustLogStrCb = extern "C" fn(*const c_char);
#[link(name = "ffmpeg_common")]
unsafe extern "C" {

    pub fn my_av_log_set_callback(level: c_int, cb: RustLogStrCb);

    pub fn startRecord(
        url: *const c_char,
        hasVDesktop: bool,
        hasVCamera: bool,
        hasASystem: bool,
        hasAMic: bool,
        isFullScreen: bool,
        isLocalTest: bool,
        watermark: *const c_char,
    ) -> i32;

    pub fn stopRecord();

}

const LOG_LEVEL: c_int = 32; // DEBUG 48,INFO 32,ERROR 16

// === 全局异步日志发送器（跨线程共享） ===
lazy_static! {
    static ref G_LOG_SENDER: Mutex<Option<Sender<String>>> = Mutex::new(None);
}

pub struct FfmpegController {
    handle: Option<JoinHandle<i32>>,
    /// 用于停止 FFmpeg 线程的发送器
    stop_tx: Option<Sender<()>>,
}

impl FfmpegController {
    pub fn new() -> Self {
        Self {
            handle: None,
            stop_tx: None,
        }
    }

    /// 异步运行 FFmpeg，返回控制通道和日志接收器
    pub fn run_async(
        &mut self,
        url: String,
        watermark: String,
        open_camera: bool,
    ) -> Receiver<String> {
        let (log_tx, log_rx) = mpsc::channel::<String>();
        let (stop_tx, stop_rx) = mpsc::channel::<()>();
        self.stop_tx = Some(stop_tx);
        // 设置全局日志发送器
        // 复制了一个 Sender 给日志回调线程用，但这个 Sender 不清空就永远“持有通道”。
        // Rust 的 Receiver 在 for log in log_rx 中只有在 所有发送者全部销毁 时，才会退出
        *G_LOG_SENDER.lock().unwrap() = Some(log_tx.clone());

        extern "C" fn async_log_callback(msg: *const c_char) {
            unsafe {
                if !msg.is_null() {
                    if let Ok(s) = CStr::from_ptr(msg).to_str() {
                        if let Some(ref tx) = *G_LOG_SENDER.lock().unwrap() {
                            let msg = s.trim_end().to_string();
                            let _ = tx.send(msg);
                        }
                    }
                }
            }
        }

        unsafe {
            my_av_log_set_callback(LOG_LEVEL, async_log_callback);
        }

        self.handle = Some(thread::spawn(move || {
            let r;
            unsafe {
                let c_url = std::ffi::CString::new(url).unwrap();
                let c_watermark = std::ffi::CString::new(watermark).unwrap();
                r = startRecord(
                    c_url.as_ptr(),
                    true,
                    open_camera,
                    false,
                    true,
                    true,
                    true,
                    c_watermark.as_ptr(),
                );
            }

            // 运行 FFmpeg 后，等待停止信号
            let _ = stop_rx.recv();
            // 上边复制了一个 清空全局 sender，防止它阻止日志线程退出
            *G_LOG_SENDER.lock().unwrap() = None;
            drop(log_tx); // 关闭日志发送器
            println!("startRecord  thread exiting");
            return r;
        }));

        log_rx
    }

    pub fn wait_stop(&mut self) -> i32 {
        unsafe { stopRecord() };
        if let Some(tx) = self.stop_tx.take() {
            let _ = tx.send(());
        }
        if let Some(h) = self.handle.take() {
            let r = h.join();
            return r.unwrap();
        }
        return 0;
    }
}
